package zmee.util;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import zmee.entity.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lijiawang
 * @Date 2022/11/8 14:20
 * @Description:访问OA接口工具类
 */
public class OARequestUtil {
    private static Log logger = LogFactory.getLog(OARequestUtil.class);
    private static Map<String, String> SYSTEM_CACHE = new HashMap<>();
    private final static OARequestUtil initialize = new OARequestUtil();

    public static void clearCache() {
        SYSTEM_CACHE.clear();
    }

    public static OARequestUtil getInitialize() {
        return initialize;
    }

    public static Map<String, Object> Regist(DynamicObject config) {
        //获取当前系统RSA加密的公钥
        RSA rsa = new RSA();
        String publicKey = rsa.getPublicKeyBase64();
        String privateKey = rsa.getPrivateKeyBase64();

        // 客户端RSA私钥
        SYSTEM_CACHE.put("LOCAL_PRIVATE_KEY", privateKey);
        // 客户端RSA公钥
        SYSTEM_CACHE.put("LOCAL_PUBLIC_KEY", publicKey);
        logger.info("LOCAL_PUBLIC_KEY" + publicKey);
        //调用ECOLOGY系统接口进行注册
        String data = HttpRequest.post(config.getString("secreturl"))
                .header("Content-Type", "application/json")
                .header("appid", config.getString("user"))
                .header("cpk", publicKey)
                .timeout(2000)
                .execute().body();
        // 打印ECOLOGY响应信息
        logger.info("testRegist()：" + data);
        Map<String, Object> datas = JSONUtil.parseObj(data);

        //ECOLOGY返回的系统公钥
        SYSTEM_CACHE.put("SERVER_PUBLIC_KEY", StrUtil.nullToEmpty((String) datas.get("spk")));
        //ECOLOGY返回的系统密钥
        SYSTEM_CACHE.put("SERVER_SECRET", StrUtil.nullToEmpty((String) datas.get("secrit")));
        return datas;
    }

    public static String getoken(DynamicObject config) {
        // 从系统缓存或者数据库中获取ECOLOGY系统公钥和Secret信息
        String secret = SYSTEM_CACHE.get("SERVER_SECRET");
        String spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY");
        if (secret == null || spk == null) {
            Map<String, Object> regist = Regist(config);
            logger.info("regist" + regist);

            secret = SYSTEM_CACHE.get("SERVER_SECRET");
            spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY");
            logger.info("为空重新赋值：  getoken - secret = " + secret + "; spk = " + spk);
        }
        logger.info("两个参数的值为：  getoken - secret = " + secret + "; spk = " + spk);
        // 公钥加密,所以RSA对象私钥为null
        RSA rsa = new RSA(null, spk);
        //对秘钥进行加密传输，防止篡改数据
        String encryptSecret = rsa.encryptBase64(secret, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);
        logger.info("encryptSecret" + encryptSecret);
        //调用ECOLOGY系统接口进行注册
        String data = HttpRequest.post(config.getString("tokenurl"))
                .header("Content-Type", "application/json")
                .header("appid", config.getString("user"))
                .header("secret", encryptSecret)
                .header("time", "3600")
                .timeout(20000)
                .execute().body();

        logger.info("testGetoken()：" + data);
        Map<String, Object> datas = JSONUtil.parseObj(data);

        //ECOLOGY返回的token
        SYSTEM_CACHE.put("SERVER_TOKEN", StrUtil.nullToEmpty((String) datas.get("token")));
        return datas.get("token").toString();
    }

    //获取人员信息
    public static String getOARequest(DynamicObject config, String jsonParams) {
        String token = "";
        try {
            token = getoken(config);
        } catch (Exception e) {
            logger.info("获取token失败" + e);
        }
        logger.info("token:" + token);

        String spk = SYSTEM_CACHE.get("SERVER_PUBLIC_KEY");
        //封装请求头参数
        RSA rsa = new RSA(null, spk);
        //对用户信息进行加密传输,暂仅支持传输OA用户ID
        String encryptUserid = rsa.encryptBase64("1", CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);

        //调用ECOLOGY系统接口
        String data = HttpRequest.post(config.getString("url"))
                .header("Content-Type", "application/json")
                .header("appid", config.getString("user"))
                .header("token", token)
                .header("userid", encryptUserid)
                .body(jsonParams)
                .timeout(18000)
                .execute().body();
        logger.warn("接口返回数据 data = " + data);
        return data;

    }

    //OA工作流地址配置
    private static DynamicObject oaflow = initialize.config("oaflow");

    public static String doCreateWorkflowRequest(String txt) {
        if (oaflow == null) {
            logger.info("===未配置相关配置===");
        }
        String body = HttpRequest.post(oaflow.getString("url"))
                .header("Content-Type", "application/xml")
                .header("apikey", oaflow.getString("user"))
                .body(txt)
                .timeout(180000)
                .execute().body();
        return body;
    }


    public static String requestProcessing(String print) {
        String txt = "";
        if (print.contains("<ns1:out>")) {
            txt = print.substring(print.indexOf("<ns1:out>") + 9, print.indexOf("</ns1:out>"));
        } else {
            txt = "创建流程失败！";
            return txt;
        }
        switch (txt) {
            case "-1":
                return "创建流程失败!";
            case "-2":
                return "没有创建权限!";
            case "-3":
                return "创建流程失败!";
            case "-4":
                return "字段或表名不正确";
            case "-5":
                return "更新流程级别失败";
            case "-6":
                return "无法创建流程待办任务";
            case "-7":
                return "流程下一节点出错，请检查流程的配置，在OA中发起流程进行测试";
            case "-8":
                return "流程节点自动赋值操作错误";
            default:
                return txt;
        }
    }

    /**
     * info  请求头
     * main  表头字段
     * mapUrl  附件
     */

    public static FrontWorkflowRequestInfoin0 getFrontWorkflowRequestInfoin0(Map<String, Object> info, Map<String, Object> main, List<Map<String, String>> mapUrl) {
        FrontWorkflowRequestInfoin0 requestInfoin0 = new FrontWorkflowRequestInfoin0();

        WorkflowRequestInfo requestInfo = new WorkflowRequestInfo();   //流程信息
        requestInfoin0.setResource(info.get("resource").toString()); //系统来源
        requestInfoin0.setUsderid(info.get("usderid").toString());  //分配号
        requestInfoin0.setAccountType(Integer.parseInt(info.get("accountType").toString()));//类型
        //传入名称
        requestInfo.setRequestName(info.get("name").toString());
        Object isnext = info.get("isnextflow");
        if (isnext != null) {
            requestInfo.setIsnextflow(Integer.parseInt(isnext.toString()));
        }
        //OA流程信息
        WorkflowBaseInfo baseInfo = new WorkflowBaseInfo();
        baseInfo.setWorkflowId(info.get("workflowId").toString());
        baseInfo.setWorkflowName(info.get("workflowName").toString());
        //表头信息
        WorkflowMainTableInfo mainTableInfo = new WorkflowMainTableInfo();
        WorkflowRequestTableRecord requestTableRecord = new WorkflowRequestTableRecord();
        requestTableRecord.setRecordOrder(1);

        List<WorkflowRequestTableField> listField = new ArrayList<>();
        //单据头字段
        for (String Str : main.keySet()) {
            WorkflowRequestTableField requestTableField = new WorkflowRequestTableField();
            Object obj = main.get(Str);
            if (obj == null) {
                continue;
            }
            requestTableField.setFieldName(Str);
            requestTableField.setFieldValue(obj.toString());
            listField.add(requestTableField);
        }
        //单据附件
        for (Map<String, String> map : mapUrl) {
            WorkflowRequestTableField requestTableField = new WorkflowRequestTableField();
            requestTableField.setFieldName(map.get("fieldName"));
            requestTableField.setFieldType(map.get("fieldType"));
            requestTableField.setFieldValue(map.get("fieldValue"));
            listField.add(requestTableField);
        }
        WorkflowRequestTableField[] requestTableFields = new WorkflowRequestTableField[listField.size()];
        for (int i = 0; i < listField.size(); i++) {
            requestTableFields[i] = listField.get(i);
        }
        requestTableRecord.setWorkflowRequestTableFields(requestTableFields);
        mainTableInfo.setRequestRecords(requestTableRecord);
        requestInfo.setWorkflowMainTableInfo(mainTableInfo);
        requestInfo.setWorkflowBaseInfo(baseInfo);
        requestInfoin0.setWorkflowRequestInfo(requestInfo);
        return requestInfoin0;
    }


    public static String workflowRequestBody(FrontWorkflowRequestInfoin0 frontWorkf) {
        StringBuffer body = new StringBuffer();//请求工作流程
        body.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:fron=\"" + oaflow.getString("secreturl") + "\" xmlns:web=\"http://webservices.workflow.weaver\">");
        body.append("<soapenv:Header/>");
        body.append("<soapenv:Body>");
        body.append("<fron:doCreateWorkflowRequest>");
        body.append("<fron:in0>");
        body.append("<web:accountType>" + frontWorkf.getAccountType() + "</web:accountType>");  //类型
        body.append("<web:userid>" + frontWorkf.getUsderid() + "</web:userid>"); //账号
        //工作流程请求信息
        WorkflowRequestInfo workflowRequestInfo = frontWorkf.getWorkflowRequestInfo();
        StringBuffer requestInfo = new StringBuffer();
        requestInfo.append("<web:workflowRequestInfo>");
        requestInfo.append("<web:requestLevel/>");
        requestInfo.append("<web:creatorId/>");
        requestInfo.append("<web:requestName>" + workflowRequestInfo.getRequestName() + "</web:requestName>");
        if (workflowRequestInfo.getIsnextflow() == 0) {
            requestInfo.append("<web:isnextflow>0</web:isnextflow>");
        }
        WorkflowBaseInfo workflowBaseInfo = workflowRequestInfo.getWorkflowBaseInfo();
        StringBuffer baseInfo = new StringBuffer();//工作流信息类
        baseInfo.append("<web:workflowBaseInfo>");
        baseInfo.append("<web:workflowId>" + workflowBaseInfo.getWorkflowId() + "</web:workflowId>");
        baseInfo.append("<web:workflowName/>");
        baseInfo.append("</web:workflowBaseInfo>");
        requestInfo.append(baseInfo);
        //单据表头信息
        WorkflowMainTableInfo workflowMainTableInfo = workflowRequestInfo.getWorkflowMainTableInfo();
        StringBuffer mainTableInfo = new StringBuffer();
        mainTableInfo.append("<web:workflowMainTableInfo>");
        mainTableInfo.append("<web:requestRecords>");
        //表头字段信息
        WorkflowRequestTableRecord record = workflowMainTableInfo.getRequestRecords();
        StringBuffer tableRecord = new StringBuffer();//表记录
        tableRecord.append("<web:WorkflowRequestTableRecord>");
        tableRecord.append("<web:recordOrder>1</web:recordOrder>");
        tableRecord.append("<web:workflowRequestTableFields>");
        //表头字段标识对应的值
        WorkflowRequestTableField[] workflowRequestTableFields = record.getWorkflowRequestTableFields();
        for (int i = 0; i < workflowRequestTableFields.length; i++) {
            WorkflowRequestTableField table = workflowRequestTableFields[i];
            StringBuffer tableField = new StringBuffer();//表记录字段
            tableField.append("<web:WorkflowRequestTableField>");
            tableField.append("<web:fieldName>" + table.getFieldName() + "</web:fieldName>");
            String fieldType = table.getFieldType();
            if (fieldType != null && !"".equals(fieldType)) {
                tableField.append("<web:fieldType>" + fieldType + "</web:fieldType>");
            }
            tableField.append("<web:fieldValue>" + table.getFieldValue() + "</web:fieldValue>");
            tableField.append("<web:edit>" + table.getEdit() + "</web:edit>");
            tableField.append("<web:view>" + table.getView() + "</web:view>");
            tableField.append("</web:WorkflowRequestTableField>");
            tableRecord.append(tableField);
        }
        tableRecord.append("</web:workflowRequestTableFields>");
        tableRecord.append("</web:WorkflowRequestTableRecord>");
        mainTableInfo.append(tableRecord);

        mainTableInfo.append("</web:requestRecords>");
        mainTableInfo.append("</web:workflowMainTableInfo>");
        requestInfo.append(mainTableInfo);
        requestInfo.append("</web:workflowRequestInfo>");
        body.append(requestInfo);
        body.append("</fron:in0>");
        body.append("</fron:doCreateWorkflowRequest>");
        body.append("</soapenv:Body>");
        body.append("</soapenv:Envelope>");
        return body.toString();
    }


    public DynamicObject config(String number) {
        DynamicObject configuration = BusinessDataServiceHelper.loadSingle("zmee_configuration", "id", new QFilter[]{new QFilter("number", QCP.equals, number)});
        if (configuration == null) {
            return null;
        }
        return BusinessDataServiceHelper.loadSingle(configuration.getPkValue(), configuration.getDynamicObjectType().getName());
    }


}
